package com.dmwork.service.work.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dmwork.common.base.result.R;
import com.dmwork.common.base.result.ResultCodeEnum;
import com.dmwork.service.base.exception.DmworkException;
import com.dmwork.service.base.model.FileUrlVo;
import com.dmwork.service.base.model.VideoListVo;
import com.dmwork.service.work.entity.*;
import com.dmwork.service.work.entity.vo.*;
import com.dmwork.service.work.entity.vo.admin.AdminWorkBaseInfoVo;
import com.dmwork.service.work.entity.vo.admin.AdminWorkQueryVo;
import com.dmwork.service.work.entity.vo.constVal.WorkPictureUpdateType;
import com.dmwork.service.work.entity.vo.constVal.WorkVideoUpdateType;
import com.dmwork.service.work.feign.CustomerFeignService;
import com.dmwork.service.work.feign.OssFileFeignService;
import com.dmwork.service.work.feign.VodVideoFeignService;
import com.dmwork.service.work.feign.WorkCollectFeignService;
import com.dmwork.service.work.mapper.WorkDescriptionMapper;
import com.dmwork.service.work.mapper.WorkMapper;
import com.dmwork.service.work.mapper.WorkPictureInfoMapper;
import com.dmwork.service.work.mapper.WorkVideoInfoMapper;
import com.dmwork.service.work.mq.sender.MessageSender;
import com.dmwork.service.work.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vdurmont.emoji.EmojiParser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 李天
 * @since 2021-03-14
 */
@Slf4j
@Transactional
@Service
public class WorkServiceImpl extends ServiceImpl<WorkMapper, Work> implements WorkService {

    @Autowired
    private WorkDescriptionMapper workDescriptionMapper;
    @Autowired
    private WorkVideoInfoMapper workVideoInfoMapper;
    @Autowired
    private WorkPictureInfoMapper workPictureInfoMapper;
    @Autowired
    private RedisTemplate<String, Serializable> redisTemplate;
    @Autowired
    private WorkCollectFeignService workCollectFeignService;
    @Autowired
    private CustomerFeignService customerFeignService;
    @Autowired
    private WorkTypeService workTypeService;

    @Autowired
    private WorkDescriptionService workDescriptionService;
    @Autowired
    private WorkPictureInfoService workPictureInfoService;
    @Autowired
    private WorkVideoInfoService workVideoInfoService;
    @Autowired
    private MessageSender messageSender;
    @Autowired
    private OssFileFeignService ossFileFeignService;
    @Autowired
    private VodVideoFeignService vodVideoFeignService;

    @Override
    public WorkDetailInfoVo getWorkDetailInfoById(String workId) {
        WorkDetailInfoVo workDetailInfoVo = new WorkDetailInfoVo();
        //1、获取work基本信息
        Work work = baseMapper.selectById(workId);
        WorkDescription workDescription = workDescriptionMapper.selectById(workId);
        WorkType workType = workTypeService.getById(work.getTypeId());
        BeanUtils.copyProperties(work, workDetailInfoVo);
        R baseInfoResult = customerFeignService.getBaseInfo(work.getCustomerId());
        workDetailInfoVo.setCustomerName((String) baseInfoResult.getData().get("customerName"));
        workDetailInfoVo.setDescription(workDescription.getDescription());
        workDetailInfoVo.setTypeName(workType.getName());

        //2、获取展示视频列表，如果视频数量不为0时才进行查询
        if (work.getVideoCount() != 0) {
            QueryWrapper<WorkVideoInfo> videoInfoQueryWrapper = new QueryWrapper<>();
            videoInfoQueryWrapper.eq("work_id", workId);
            List<WorkVideoInfo> workVideoInfoList = workVideoInfoMapper.selectList(videoInfoQueryWrapper);
            workDetailInfoVo.setWorkVideoInfoList(workVideoInfoList);
        }

        //3、获取展示图片列表，如果图片数量不为0时才进行查询
        if (work.getPictureCount() != 0) {
            QueryWrapper<WorkPictureInfo> pictureInfoQueryWrapper = new QueryWrapper<>();
            pictureInfoQueryWrapper.eq("work_id", workId);
            List<WorkPictureInfo> workPictureInfoList = workPictureInfoMapper.selectList(pictureInfoQueryWrapper);
            workDetailInfoVo.setWorkPictureInfoList(workPictureInfoList);
        }

        //4、获取作品收藏数
        Integer count = workCollectFeignService.getCollectCountByWorkId(workId);
        if (count < 0) {
            throw new DmworkException(ResultCodeEnum.SELECT_WORK_COLLECT_COUNT_ERROR);
        } else {
            workDetailInfoVo.setCollectCount(count);
        }

        return workDetailInfoVo;
    }

    @Override
    public String publishWork(String id, WorkPublishInfoVo workPublishInfoVo) {
        //保存用户基本信息
        Work work = new Work();
        BeanUtils.copyProperties(workPublishInfoVo, work);
        work.setCustomerId(id);
        work.setUpdateTime(new Date());
        baseMapper.insert(work);

        //保存作品描述信息
        WorkDescription workDescription = new WorkDescription();
        workDescription.setId(work.getId());
        workDescription.setDescription(workPublishInfoVo.getDescription());
        workDescriptionMapper.insert(workDescription);

        //批量保存视频信息
        List<WorkVideoInfo> workVideoInfoList = workPublishInfoVo.getWorkVideoInfoList();
        if (!workVideoInfoList.isEmpty()) {
            //更新作品表中的video_count
            work.setVideoCount(workVideoInfoList.size());
            //workVideoInfo和Work主键相同
            for (WorkVideoInfo workVideoInfo : workVideoInfoList) {
                workVideoInfo.setWorkId(work.getId());
                workVideoInfoMapper.insert(workVideoInfo);
            }
        }

        //保存图片信息
        List<WorkPictureInfo> workPictureInfoList = workPublishInfoVo.getWorkPictureInfoList();
        if (!workPictureInfoList.isEmpty()) {
            //更新作品表中的picture_count
            work.setPictureCount(workPictureInfoList.size());
            //主键和Work相同
            for (WorkPictureInfo workPictureInfo : workPictureInfoList) {
                workPictureInfo.setWorkId(work.getId());
                workPictureInfoMapper.insert(workPictureInfo);
            }
        }
        //最后更新work
        baseMapper.updateById(work);

        return work.getId();
    }

    @Override
    public Page<Work> getInfoPage(String customerId, Integer page, Integer limit) {
        Page<Work> workPage = new Page<Work>(page, limit);
        QueryWrapper<Work> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("customer_id", customerId);
        workPage = baseMapper.selectPage(workPage, queryWrapper);
        List<Work> workList = workPage.getRecords();
        if (workList.size() == 0) {
            workPage.setRecords(workList);
            return workPage;
        }
        //获取所有作品的收藏数
        List<String> workIdList = new ArrayList<>();
        for (Work work : workList) {
            workIdList.add(work.getId());
        }
        Map<String, Integer> resultMap = workCollectFeignService.getBatchCollectCountByWorkIdList(workIdList);
        for (Work work : workList) {
            Integer count = resultMap.get(work.getId());
            work.setCollectCount(count);
        }
        workPage.setRecords(workList);
        return workPage;
    }

    @Override
    public Page<WorkBaseInfoVo> getWorkPage(WorkQueryVo workQueryVo, Integer page, Integer limit) {
        Page<WorkBaseInfoVo> selectPage = new Page<>(page, limit);
        QueryWrapper<WorkBaseInfoVo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dw.is_deleted", 0);
        //如果查询对象为空，则直接分页查询
        if (workQueryVo == null) {
            selectPage.setRecords(baseMapper.selectBaseInfoPage(selectPage, queryWrapper));
            return selectPage;
        } else {
            log.info(workQueryVo.toString());
            // 查询字符串
            if (!StringUtils.isEmpty(workQueryVo.getQueryString())) {
                log.info(workQueryVo.getQueryString());
                queryWrapper.like("title", workQueryVo.getQueryString());
            }
            //作品指定类型
            if (!StringUtils.isEmpty(workQueryVo.getTypeId())) {
                queryWrapper.eq("dw.type_id", workQueryVo.getTypeId());
            }
            //按热度排序：0->降序，1->升序
            if (workQueryVo.getHot() != null) {
                if (workQueryVo.getHot() == 0) {
                    queryWrapper.orderByDesc("hot");
                } else if (workQueryVo.getHot() == 1) {
                    queryWrapper.orderByAsc("hot");
                }
            }
            // 按最新发布排序，传个数值就可以
            if (workQueryVo.getLatest() != null) {
                queryWrapper.orderByDesc("dw.update_time");
            }
            if (workQueryVo.getCollectMost() != null) {
                queryWrapper.orderByDesc("collect_count");
            }

            List<WorkBaseInfoVo> workBaseInfoVoList = baseMapper.selectBaseInfoPage(selectPage, queryWrapper);

            selectPage.setRecords(workBaseInfoVoList);
            return selectPage;
        }
    }

    @Override
    public List<WorkBaseInfoVo> getHotList(Integer count, String typeId) {
        Page<WorkBaseInfoVo> page = new Page<>(1, count);
        QueryWrapper<WorkBaseInfoVo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dw.type_id", typeId);
        queryWrapper.eq("dw.is_deleted", 0);
        queryWrapper.orderByDesc("hot");
        return baseMapper.selectBaseInfoPage(page, queryWrapper);
    }

    @Override
    public Page<WorkBaseInfoVo> getWorkBaseInfoPageByCustomerId(String customerId, Integer page, Integer limit) {
        Page<WorkBaseInfoVo> selectPage = new Page<>(page, limit);
        QueryWrapper<WorkBaseInfoVo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dw.is_deleted", 0);
        queryWrapper.eq("customer_id", customerId);
        //默认按照发布时间排序
        queryWrapper.orderByDesc("dw.gmt_modified");
        List<WorkBaseInfoVo> workBaseInfoVoList = baseMapper.selectBaseInfoPage(selectPage, queryWrapper);
        if (workBaseInfoVoList.size() == 0) {
            selectPage.setRecords(workBaseInfoVoList);
            return selectPage;
        }
        //获取所有作品的收藏数
        List<String> workIdList = new ArrayList<>();
        for (WorkBaseInfoVo workBaseInfoVo : workBaseInfoVoList) {
            workIdList.add(workBaseInfoVo.getId());
        }
        Map<String, Integer> resultMap = workCollectFeignService.getBatchCollectCountByWorkIdList(workIdList);
        for (WorkBaseInfoVo workBaseInfoVo : workBaseInfoVoList) {
            Integer count = resultMap.get(workBaseInfoVo.getId());
            workBaseInfoVo.setCollectCount(count);
        }
        selectPage.setRecords(workBaseInfoVoList);
        return selectPage;
    }

    @Override
    public List<WorkBaseInfoVo> getWorkBaseInfoListByIds(List<String> workIdList) {
        QueryWrapper<WorkBaseInfoVo> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("dw.id", workIdList).eq("dw.is_deleted", 0);
        List<WorkBaseInfoVo> workBaseInfoVoList = baseMapper.getWorkBaseInfoListByIds(queryWrapper);
        //获取所有作品的收藏数
        Map<String, Integer> resultMap = workCollectFeignService.getBatchCollectCountByWorkIdList(workIdList);
        for (WorkBaseInfoVo workBaseInfoVo : workBaseInfoVoList) {
            Integer count = resultMap.get(workBaseInfoVo.getId());
            workBaseInfoVo.setCollectCount(count);
        }
        return workBaseInfoVoList;
    }

    @Override
    public void modifyBatchWorkCollectCount(List<String> workIdList, Integer flag) {
        List<Work> workList = baseMapper.selectBatchIds(workIdList);
        if (flag == 0) {
            for (Work work : workList) {
                work.setCollectCount(work.getCollectCount() - 1);
                baseMapper.updateById(work);
            }
        } else if (flag == 1) {
            for (Work work : workList) {
                work.setCollectCount(work.getCollectCount() + 1);
                baseMapper.updateById(work);
            }
        }
    }

    @Override
    public void increaseCollectCount(String workId) {
        baseMapper.increaseCollectCount(workId);
    }

    @Override
    public void decreaseCollectCount(String workId) {
        baseMapper.decreaseCollectCount(workId);
    }

    @Override
    public Page<AdminWorkBaseInfoVo> getAdminWorkBaseInfoPage(Integer page, Integer limit, AdminWorkQueryVo workQueryVo) {
        Page<Work> workPage = new Page<>(page, limit);
        QueryWrapper<Work> queryWrapper = new QueryWrapper<>();
        if (!StringUtils.isEmpty(workQueryVo.getTitleQs())) { //作品标题字段条件
            queryWrapper.like("title", workQueryVo.getTitleQs());
        }
        if (!StringUtils.isEmpty(workQueryVo.getTypeId())) { //作品类型条件
            queryWrapper.eq("type_id", workQueryVo.getTypeId());
        }
        if (!StringUtils.isEmpty(workQueryVo.getHot())) { //按热度的排序条件
            if (workQueryVo.getHot() == 0) {
                queryWrapper.orderByDesc("hot");
            } else if (workQueryVo.getHot() == 1) {
                queryWrapper.orderByAsc("hot");
            }
        }
        if (StringUtils.isEmpty(workQueryVo.getTime()) || workQueryVo.getTime() == 0) { //按发布时间的条件
            queryWrapper.orderByDesc("gmt_create");
        } else {
            queryWrapper.orderByAsc("gmt_create");
        }
        workPage = baseMapper.selectPage(workPage, queryWrapper);

        if (workPage.getTotal() == 0) {
            return new Page<>();
        }

        //获取作品所属用户的用户名以及作品收藏数
        List<String> customerIdList = new ArrayList<>(); //用户id列表
        List<String> workIdList = new ArrayList<>(); //作品id列表
        List<String> typeIdList = new ArrayList<>(); //作品类型id列表
        for (Work work : workPage.getRecords()) {
            customerIdList.add(work.getCustomerId());
            workIdList.add(work.getId());
            typeIdList.add(work.getTypeId());
        }
        //获取用户名和id
        R customerBriefInfoListResult = customerFeignService.getBriefInfoList(customerIdList);
        HashMap<String, List<String>> customerInfoMap = (HashMap<String, List<String>>) customerBriefInfoListResult.getData().get("result");

        //获取作品收藏数
        Map<String, Integer> workCollectResultMap = workCollectFeignService.getBatchCollectCountByWorkIdList(workIdList);

        //获取作品类型信息
        List<WorkType> workTypeList = workTypeService.list(new QueryWrapper<WorkType>().in("id", typeIdList));

        //组装数据
        List<AdminWorkBaseInfoVo> adminWorkBaseInfoVoList = new ArrayList<>((int) workPage.getTotal());
        for (Work work : workPage.getRecords()) {
            AdminWorkBaseInfoVo adminWorkBaseInfoVo = new AdminWorkBaseInfoVo();
            //转换作品中标题的Emoji
            work.setTitle(EmojiParser.parseToUnicode(work.getTitle()));
            BeanUtils.copyProperties(work, adminWorkBaseInfoVo);
            adminWorkBaseInfoVo.setCustomerName(customerInfoMap.get(work.getCustomerId()).get(0)); //设置用户名
            adminWorkBaseInfoVo.setCollectCount(workCollectResultMap.get(work.getId())); //设置作品收藏数
            for (WorkType workType : workTypeList) { //设置作品类型名称
                if (work.getTypeId().equals(workType.getId())) {
                    adminWorkBaseInfoVo.setTypeName(workType.getName());
                    break;
                }
            }
            adminWorkBaseInfoVoList.add(adminWorkBaseInfoVo);
        }

        Page<AdminWorkBaseInfoVo> adminWorkBaseInfoVoPage = new Page<>();
        adminWorkBaseInfoVoPage.setRecords(adminWorkBaseInfoVoList);
        adminWorkBaseInfoVoPage.setTotal(workPage.getTotal());

        return adminWorkBaseInfoVoPage;
    }

    @Override
    public void removeWork(String workId) {
        //删除作品基本信息
        Work work = baseMapper.selectById(workId);
        baseMapper.deleteById(workId);

        //删除作品详情信息
        workDescriptionService.removeById(workId);

        //删除作品封面以及展示图片信息
        List<String> pictureUrlList = workPictureInfoService.getPictureUrlListByWorkId(workId);
        pictureUrlList.add(work.getCover());

        workPictureInfoService.removeByWorkId(workId);

        //删除作品视频信息
        workVideoInfoService.removeVideoSourceByWorkId(workId);

        workVideoInfoService.removeByWorkId(workId);

        //让OSS删除这些图片
        messageSender.sendBatchFileRemoveMessage(pictureUrlList, new HashMap<>());

        //删除作品投稿产生的动态
        messageSender.sendWorkPublishFeedRemoveMessage(workId, new HashMap<>());
    }

    @Override
    public void updateWorkInfo(WorkUpdateInfoVo workUpdateInfoVo) {
        //转换作品中标题和简介的Emoji
        workUpdateInfoVo.setTitle(EmojiParser.parseToAliases(workUpdateInfoVo.getTitle()));
        workUpdateInfoVo.setDescription(EmojiParser.parseToAliases(workUpdateInfoVo.getDescription()));

        //TODO 更新作品图片
        List<String> workPictureUrlList = new ArrayList<>();
        List<WorkPictureUpdateVo> workPictureUpdateVoList = workUpdateInfoVo.getWorkPictureUpdateVoList();
        if (workPictureUpdateVoList != null && !workPictureUpdateVoList.isEmpty()) {
            List<WorkPictureInfo> increasePictureList = new ArrayList<>();
            List<String> workPictureIdList = new ArrayList<>();
            for (WorkPictureUpdateVo w : workPictureUpdateVoList) {
                if (w.getUpdateType() == WorkPictureUpdateType.ADD) {
                    increasePictureList.add(WorkPictureInfo.builder()
                            .workId(workUpdateInfoVo.getId())
                            .pictureUrl(w.getPictureUrl())
                            .build());
                } else if (w.getUpdateType() == WorkPictureUpdateType.REMOVE) {
                    workPictureUrlList.add(w.getPictureUrl());
                    if (!StringUtils.isEmpty(w.getId())) {
                        workPictureIdList.add(w.getId());
                    }
                }
            }
            //先在数据库做图片信息的新增与删除工作
            //删除数据
            if (!workPictureIdList.isEmpty()) {
                workPictureInfoMapper.deleteBatchIds(workPictureIdList);
            }
            //新增数据
            if (!increasePictureList.isEmpty()) {
                workPictureInfoService.saveBatch(increasePictureList);
            }
        }

        // 更新作品视频
        List<String> workVideoSourceIdList = new ArrayList<>();
        List<WorkVideoUpdateVo> workVideoUpdateVoList = workUpdateInfoVo.getWorkVideoUpdateVoList();
        if (workVideoUpdateVoList != null && !workVideoUpdateVoList.isEmpty()) {
            List<WorkVideoInfo> workVideoInfoList = new ArrayList<>();
            List<String> workVideoIdList = new ArrayList<>();
            for (WorkVideoUpdateVo w : workVideoUpdateVoList) {
                if (w.getUpdateType() == WorkVideoUpdateType.ADD_OR_UPDATE) {
                    workVideoInfoList.add(WorkVideoInfo.builder()
                            .workId(workUpdateInfoVo.getId())
                            .title(w.getTitle())
                            .videoSourceId(w.getVideoSourceId())
                            .build());
                } else if (w.getUpdateType() == WorkVideoUpdateType.REMOVE) {
                    workVideoSourceIdList.add(w.getVideoSourceId());
                    if (!StringUtils.isEmpty(w.getId())) {
                        workVideoIdList.add(w.getId());
                    }
                }
            }
            //先在数据库做视频信息的增删改工作
            //新增或更新
            if (!workVideoInfoList.isEmpty()) {
                workVideoInfoService.saveOrUpdateBatch(workVideoInfoList);
            }
            //删除视频信息
            if (!workVideoIdList.isEmpty()) {
                workVideoInfoService.removeByIds(workVideoIdList);
            }
        }

        Work work = new Work();

        BeanUtils.copyProperties(workUpdateInfoVo, work);
        work.setUpdateTime(new Date());        //更新基本信息
        work.setPictureCount(workPictureInfoMapper.selectCount(new QueryWrapper<WorkPictureInfo>().eq("work_id", workUpdateInfoVo.getId())));
        work.setVideoCount(workVideoInfoMapper.selectCount(new QueryWrapper<WorkVideoInfo>().eq("work_id", workUpdateInfoVo.getId())));
        baseMapper.updateById(work);
        //更新作品介绍
        WorkDescription workDescription = new WorkDescription();
        workDescription.setId(workUpdateInfoVo.getId());
        workDescription.setDescription(workUpdateInfoVo.getDescription());
        workDescriptionService.updateById(workDescription);

        //OpenFeign远程删除图片与视频信息
        if (!workPictureUrlList.isEmpty()) {
            ossFileFeignService.removeBatchFile(FileUrlVo.builder().urlList(workPictureUrlList).build());
        }
        if (!workVideoSourceIdList.isEmpty()) {
            vodVideoFeignService.removeVideoByIdList(VideoListVo.builder().videoIdList(workVideoSourceIdList).build());
        }
    }
}
